package com.sl.core.engine.transfer;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.sl.core.domain.dto.JsonMappingFieldDefine;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.StringJoiner;

public class MappingFiledDefineToJoltDslTransfer {

    /**
     * 将JsonMappingFieldDefine列表转换为Jolt DSL字符串
     * @param fieldDefineList JsonMappingFieldDefine列表
     * @return Jolt DSL字符串
     */
    public static String transfer(List<JsonMappingFieldDefine> fieldDefineList) {
        buildParent(fieldDefineList, null);
        buildJsonPath(fieldDefineList, "$");
        List<JsonMappingFieldDefine> sourceFieldDefineList = Lists.newArrayList();
        jsonMappingPathTo(fieldDefineList, sourceFieldDefineList);
        buildParent(sourceFieldDefineList, null);
        buildJsonPath(sourceFieldDefineList, "$");

        if (CollUtil.isEmpty(sourceFieldDefineList)) {
            return StrUtil.EMPTY;
        }

        return buildJoltDslString(sourceFieldDefineList, fieldDefineList);
    }

    /**
     * 构建Jolt DSL字符串
     * @param sourceFieldDefineList 源字段定义列表
     * @param fieldDefineList 字段定义列表
     * @return Jolt DSL字符串
     */
    private static String buildJoltDslString(List<JsonMappingFieldDefine> sourceFieldDefineList, List<JsonMappingFieldDefine> fieldDefineList) {
        StringJoiner stringBuilder = new StringJoiner("\n");
        stringBuilder.add("[");
        stringBuilder.add("{");
        stringBuilder.add("'operation': 'shift',");
        stringBuilder.add("'spec': {");
        stringBuilder.add(fieldDefineToStr(sourceFieldDefineList, fieldDefineList));
        stringBuilder.add("}");
        stringBuilder.add("}");
        stringBuilder.add("]");
        return stringBuilder.toString();
    }

    /**
     * 将mappingJsonPath转换为JsonMappingFieldDefine列表
     * @param target 目标列表
     * @param source 源列表
     */
    private static void jsonMappingPathTo(List<JsonMappingFieldDefine> target, List<JsonMappingFieldDefine> source) {
        for (JsonMappingFieldDefine jsonMappingFieldDefine : target) {
            String mappingJsonPath = jsonMappingFieldDefine.getMappingJsonPath();
            List<JsonMappingFieldDefine> childrens = jsonMappingFieldDefine.getChildren();

            if (StrUtil.isNotBlank(mappingJsonPath)) {
                addBuild(mappingJsonPath, source);
            }

            // 递归处理子节点
            if (CollUtil.isNotEmpty(childrens)) {
                jsonMappingPathTo(childrens, source);
            }
        }
    }

    /**
     * 根据mappingJsonPath构建JsonMappingFieldDefine列表
     * @param mappingJsonPath mappingJsonPath
     * @param source 源列表
     */
    private static void addBuild(String mappingJsonPath, List<JsonMappingFieldDefine> source) {
        List<String> split = StrUtil.split(mappingJsonPath, ".");
        String path = "";
        JsonMappingFieldDefine parent = null;

        for (String s : split) {
            if (StrUtil.equalsAnyIgnoreCase(s, "$")) {
                path = StrUtil.EMPTY;
                path += s;
                continue;
            }

            JsonMappingFieldDefine newJson = createJsonMappingFieldDefine(s, path);
            newJson.setParent(parent); // 设置父节点关系

            JsonMappingFieldDefine existingNode = getJsonMappingFieldDefine(newJson.getPath(), source);
            if (ObjectUtil.isNotNull(existingNode)) {
                parent = existingNode; // 更新当前父节点为已存在的节点
                continue;
            }

            if (ObjectUtil.isNull(parent)) {
                source.add(newJson);
            } else {
                addChild(parent, newJson);
            }

            parent = newJson; // 更新当前父节点为新创建的节点
            path = newJson.getPath();
        }
    }

    /**
     * 创建JsonMappingFieldDefine对象
     * @param s 字段代码字符串
     * @param path 父路径
     * @return JsonMappingFieldDefine对象
     */
    private static JsonMappingFieldDefine createJsonMappingFieldDefine(String s, String path) {
        JsonMappingFieldDefine newJson = new JsonMappingFieldDefine();
        String fieldCode;
        if (StrUtil.contains(s, "[*]")) {
            String replace = StrUtil.replace(s, "[*]", "");
            path += "." + replace;
            fieldCode = replace;
            newJson.setIsArrayFlag(true);
        } else {
            path += "." + s;
            fieldCode = s;
            newJson.setIsArrayFlag(false);
        }
        newJson.setFieldCode(fieldCode);
        newJson.setFieldName(fieldCode);
        newJson.setFieldType("String");
        newJson.setFieldDesc(fieldCode);
        newJson.setPath(path);
        // 设置mappingPath为完整路径
        newJson.setMappingPath(path);
        return newJson;
    }

    /**
     * 添加子节点到父节点
     * @param parent 父节点
     * @param child 子节点
     */
    private static void addChild(JsonMappingFieldDefine parent, JsonMappingFieldDefine child) {
        List<JsonMappingFieldDefine> children = parent.getChildren();
        if (ObjectUtil.isNull(children)) {
            children = Lists.newArrayList();
        }
        children.add(child);
        parent.setChildren(children);
    }

    /**
     * 根据父路径查找JsonMappingFieldDefine对象
     * @param parentPath 父路径
     * @param source 源列表
     * @return JsonMappingFieldDefine对象
     */
    private static JsonMappingFieldDefine getJsonMappingFieldDefine(String parentPath, List<JsonMappingFieldDefine> source) {
        for (JsonMappingFieldDefine jsonMappingFieldDefine : source) {
            String path1 = jsonMappingFieldDefine.getPath();
            if (StrUtil.equalsAnyIgnoreCase(parentPath, path1)) {
                return jsonMappingFieldDefine;
            }
            List<JsonMappingFieldDefine> children = jsonMappingFieldDefine.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                JsonMappingFieldDefine result = getJsonMappingFieldDefine(parentPath, children);
                if (ObjectUtil.isNotNull(result)) {
                    return result;
                }
            }
        }
        return null;
    }

    /**
     * 构建JsonPath
     * @param fieldDefineList 字段定义列表
     * @param jsonPath 当前JsonPath
     */
    private static void buildJsonPath(List<JsonMappingFieldDefine> fieldDefineList, String jsonPath) {
        for (JsonMappingFieldDefine jsonMappingFieldDefine : fieldDefineList) {
            String fieldCode = jsonMappingFieldDefine.getFieldCode();
            String concat = StrUtil.concat(true, jsonPath, ".", fieldCode);
            jsonMappingFieldDefine.setJsonPath(concat);

            List<JsonMappingFieldDefine> children = jsonMappingFieldDefine.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                buildJsonPath(children, concat);
            }
        }
    }

    /**
     * 构建父节点关系
     * @param fieldDefineList 字段定义列表
     * @param parent 父节点
     */
    private static void buildParent(List<JsonMappingFieldDefine> fieldDefineList, JsonMappingFieldDefine parent) {
        for (JsonMappingFieldDefine jsonMappingFieldDefine : fieldDefineList) {
            jsonMappingFieldDefine.setParent(parent);
            List<JsonMappingFieldDefine> children = jsonMappingFieldDefine.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                buildParent(children, jsonMappingFieldDefine);
            }
        }
    }

    /**
     * 将字段定义列表转换为字符串
     * @param fieldDefineList 字段定义列表
     * @param convertRelationDTO 转换关系列表
     * @return 转换后的字符串
     */
    private static String fieldDefineToStr(List<JsonMappingFieldDefine> fieldDefineList, List<JsonMappingFieldDefine> convertRelationDTO) {
        StringJoiner stringBuilder = new StringJoiner("\n");
        for (int i = 0; i < fieldDefineList.size(); i++) {
            JsonMappingFieldDefine fieldDefine = fieldDefineList.get(i);
            String line = buildFieldDefineLine(fieldDefine, convertRelationDTO, i, fieldDefineList.size());
            stringBuilder.add(line);
        }
        return stringBuilder.toString();
    }

    /**
     * 构建单个字段定义的行字符串
     * @param fieldDefine 字段定义
     * @param convertRelationDTO 转换关系列表
     * @param index 当前索引
     * @param size 列表大小
     * @return 行字符串
     */
    private static String buildFieldDefineLine(JsonMappingFieldDefine fieldDefine, List<JsonMappingFieldDefine> convertRelationDTO, int index, int size) {
        String fromName = fieldDefine.getFieldName();
        Boolean fromArray = fieldDefine.isArray();
        List<JsonMappingFieldDefine> obj = fieldDefine.getChildren();
        String fromPath = fieldDefine.getPath();

        StringJoiner stringJoiner = new StringJoiner(",");
        List<JsonMappingFieldDefine> jsonMappingFieldDefine = findTarget(convertRelationDTO, fromPath);

        // 如果没有找到目标，使用默认的映射路径
        if (CollUtil.isEmpty(jsonMappingFieldDefine)) {
            String defaultPath = fromPath.replaceFirst("\\$\\.", "");
            stringJoiner.add("'" + defaultPath + "'");
        } else {
            for (JsonMappingFieldDefine target : jsonMappingFieldDefine) {
                String joltPathp = buildJoltPath(target, fieldDefine);
                if (StrUtil.isNotBlank(joltPathp)) {
                    stringJoiner.add("'" + joltPathp + "'");
                }
            }
        }

        String joltPathp = "[" + stringJoiner + "]";
        if (CollUtil.isEmpty(obj)) {
            return buildLeafLine(fromName, joltPathp, index, size);
        } else {
            return buildObjectLine(fromName, fromArray, obj, convertRelationDTO, index, size);
        }
    }

    /**
     * 构建叶子节点的行字符串
     * @param fromName 字段名
     * @param joltPathp Jolt路径
     * @param index 当前索引
     * @param size 列表大小
     * @return 行字符串
     */
    private static String buildLeafLine(String fromName, String joltPathp, int index, int size) {
        if (index >= size - 1) {
            if (StrUtil.isNotBlank(joltPathp)) {
                return "'" + fromName + "':" + joltPathp;
            } else {
                return "'" + fromName + "':null";
            }
        } else {
            if (StrUtil.isNotBlank(joltPathp)) {
                return "'" + fromName + "':" + joltPathp + ",";
            } else {
                return "'" + fromName + "':null,";
            }
        }
    }

    /**
     * 构建对象节点的行字符串
     * @param fromName 字段名
     * @param fromArray 是否为数组
     * @param obj 子节点列表
     * @param convertRelationDTO 转换关系列表
     * @param index 当前索引
     * @param size 列表大小
     * @return 行字符串
     */
    private static String buildObjectLine(String fromName, Boolean fromArray, List<JsonMappingFieldDefine> obj, List<JsonMappingFieldDefine> convertRelationDTO, int index, int size) {
        StringJoiner stringBuilder = new StringJoiner("\n");
        stringBuilder.add("'" + fromName + "':{");
        if (BooleanUtil.isTrue(fromArray)) {
            stringBuilder.add("'*':{");
        }
        String s = fieldDefineToStr(obj, convertRelationDTO);
        stringBuilder.add(s);
        if (BooleanUtil.isTrue(fromArray)) {
            stringBuilder.add("}");
        }
        if (index >= size - 1) {
            stringBuilder.add("}");
        } else {
            stringBuilder.add("},");
        }
        return stringBuilder.toString();
    }

    /**
     * 构建Jolt路径
     * @param target 目标字段定义
     * @param fieldDefine 源字段定义
     * @return Jolt路径
     */
    private static String buildJoltPath(JsonMappingFieldDefine target, JsonMappingFieldDefine fieldDefine) {
        // 使用mappingPath而不是jsonPath，因为mappingPath包含完整路径信息
        String jsonPath = target.getMappingPath();
        int count = StringUtils.countMatches(jsonPath, "[*]");
        if (count > 0) {
            Integer s = 999;
            for (int j = 0; j < count; j++) {
                int indexByFrom = findIndexByFrom(fieldDefine, 0, 0, s);
                if (BooleanUtil.isTrue(fieldDefine.isArray()) && indexByFrom != 0) {
                    indexByFrom = indexByFrom - 1;
                }
                s = indexByFrom;

                if (s == 0) {
                    jsonPath = StrUtil.replaceFirst(jsonPath, "[*]", "[0]");
                } else {
                    jsonPath = StrUtil.replaceFirst(jsonPath, "[*]", "[&" + indexByFrom + "]");
                }
            }
        }
        if (BooleanUtil.isFalse(fieldDefine.isArray())) {
            JsonMappingFieldDefine fromParent = fieldDefine.getParent();
            if (ObjectUtil.isNotNull(fromParent) && BooleanUtil.isFalse(fromParent.isArray())) {
                jsonPath = jsonPath.replace("[&1]", "[0]");
            }
        }
        jsonPath = StrUtil.replace(jsonPath, "$.", "");
        return jsonPath;
    }

    /**
     * 查找数组索引
     * @param fieldDefine 字段定义
     * @param currentIndex 当前索引
     * @param indexArrayIndex 数组索引
     * @param useIndex 使用的索引
     * @return 数组索引
     */
    private static int findIndexByFrom(JsonMappingFieldDefine fieldDefine, int currentIndex, int indexArrayIndex, int useIndex) {
        if (ObjectUtil.isNull(fieldDefine)) {
            return indexArrayIndex;
        }
        Boolean isArray = fieldDefine.getIsArrayFlag();
        int j = currentIndex;
        if (BooleanUtil.isTrue(isArray)) {
            j = currentIndex + 2;
            indexArrayIndex = currentIndex;
        } else {
            j++;
        }
        if (useIndex <= j) {
            return indexArrayIndex;
        }
        JsonMappingFieldDefine parent = fieldDefine.getParent();
        return findIndexByFrom(parent, j, indexArrayIndex, useIndex);
    }

    /**
     * 根据路径查找目标字段定义列表
     * @param convertRelationDTO 转换关系列表
     * @param findByPath 查找路径
     * @return 目标字段定义列表
     */
    private static List<JsonMappingFieldDefine> findTarget(List<JsonMappingFieldDefine> convertRelationDTO, String findByPath) {
        List<JsonMappingFieldDefine> m = Lists.newArrayList();
        for (JsonMappingFieldDefine mappingFieldDefine : convertRelationDTO) {
            List<JsonMappingFieldDefine> obj = mappingFieldDefine.getChildren();
            String mappingPath = mappingFieldDefine.getMappingPath();

            if (StrUtil.equals(mappingPath, findByPath)) {
                m.add(mappingFieldDefine);
            }

            if (CollUtil.isNotEmpty(obj)) {
                List<JsonMappingFieldDefine> target = findTarget(obj, findByPath);
                if (CollUtil.isNotEmpty(target)) {
                    m.addAll(target);
                }
            }
        }
        return m;
    }

    public static void main(String[] args) {
        String url = "https://www.skylinewebcams.com/zh/webcam/canada/british-columbia/campbell-river/campbell-river.html";
        try {
            String s = HttpUtil.get(url);
            System.out.println(s);
        } catch (Exception e) {
            System.err.println("请求URL时发生错误: " + e.getMessage());
        }
        String mappingJsonPath = "$.user[*].address[*].person.pwd[*].add.ge";
        List<JsonMappingFieldDefine> source = Lists.newArrayList();
        addBuild(mappingJsonPath, source);
        System.out.println("x");
    }
}